﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;

namespace Engine.NetClasses
{
    public class DataReader
    {

        /// <summary>
        /// 2 bytes of length
        /// </summary>
        public byte[] len = { 0x00, 0x00 };
        public bool lengthRead = false;
        /// <summary>
        /// How many bytes are received from client
        /// </summary>
        public int received = 0;

        /// <summary>
        /// Buffer, containing data from client
        /// </summary>
        public byte[] buf = null;
        public bool one = false;
        void docopuData(byte[] data, int offset, int stop)
        {
            int size = BitConverter.ToInt16(len, 0);
            int startpoint = 0;
            int stopPoint = stop;
            for (int i = offset + startpoint; i < stop; i++)
            {
                buf[2 + received++] = data[i];
            }
            if (2 + received > BitConverter.ToInt16(len, 0))
            {
                received = 0;
            }
            else
            {

            }
        }
        public byte[][] receiveData(byte[] data, int offset, int count)
        {
            List<byte[]> tmp = new List<byte[]>(0);
            if (buf == null)
            {
                int max = offset + count;
                bool oneThis = false;
                while (BitConverter.ToInt16(data, offset) > 0 && offset <= max)
                {

                     
                     if (!oneThis)
                     {
                         if (one)
                         {
                             len[1] = data[offset + 0];
                             offset--;
                             one = false;
                         }
                         else
                         {
                             len[0] = data[offset + 0];
                             len[1] = data[offset + 1];
                         }

                         buf = new byte[BitConverter.ToInt16(len, 0) + 2];
                         int stop = 2 + offset + BitConverter.ToInt16(len, 0);
                         if (stop > max)
                         {
                             stop = max;
                         }
                         buf[0] = len[0];
                         buf[1] = len[1];
                         docopuData(data, offset + 2, stop);
                         if (received == 0)
                         {
                             tmp.Add(buf);
                             buf = null;
                             offset += 2 + BitConverter.ToInt16(len, 0);
                             if (max - offset == 1)
                             {
                                 oneThis = true;
                             }
                         }
                         else
                         {
                             offset += 2 + BitConverter.ToInt16(len, 0);
                             if (max - offset == 1)
                             {
                                 oneThis = true;
                             }
                         }
                     }
                     else
                     {
                         len[0] = data[offset + 0];
                         offset = max + 1;
                         one = true;
                     }

                }
            }
            else
            {
                int max = offset + count;
                int offsetN = offset + (BitConverter.ToInt16(len, 0) - received);
                docopuData(data, offset, offset + (BitConverter.ToInt16(len, 0) - received));
                if (received == 0)
                {
                    tmp.Add(buf);
                    buf = null;
                    // offset += 2 + BitConverter.ToInt16(len, 0);
                }
                else
                {
                    //offset =max;
                }
                while (BitConverter.ToInt16(data, offsetN) > 0 && offsetN <= max)
                {


                    len[0] = data[offsetN + 0];
                    if (!one)
                    {
                        len[1] = data[offsetN + 1];



                        buf = new byte[BitConverter.ToInt16(len, 0) + 2];
                        int stop = 2 + offsetN + BitConverter.ToInt16(len, 0);
                        if (stop > max)
                        {
                            stop = max;
                        }
                        buf[0] = len[0];
                        buf[1] = len[1];
                        docopuData(data, offsetN + 2, stop);
                        if (received == 0)
                        {
                            tmp.Add(buf);
                            buf = null;
                            offsetN += 2 + BitConverter.ToInt16(len, 0);
                            if (max - offsetN == 1)
                            {
                                one = true;
                            }
                        }
                        else
                        {

                            offsetN += 2 + BitConverter.ToInt16(len, 0);
                            if (max - offsetN == 1)
                            {
                                one = true;
                            }
                        }
                    }
                    else
                    {
                        offsetN = max+1;
                    }
                }
            }
            if (tmp.Count > 0)
            {
                return tmp.ToArray();
            }
            else
            {
                return null;
            }
        }


        public byte[][] read(byte[] data, int offset, int count, int transfer)
        {
            List<byte[]> tmp = new List<byte[]>(0);

            while (count>0)
            {
                //check length if 0 read curent
                if (BitConverter.ToInt16(len, 0) == 0 || !lengthRead)
                {
                    if (len[0] == 0)
                    {
                        len[0] = data[offset];
                        lengthRead = false;
                        if (!one)
                        {
                            one = true;
                        }
                        else
                        {
                            count = 0;
                            break;
                        }
                        
                    }
                    else
                    {
                        len[1] = data[offset];
                        lengthRead = true;
                        one = false;
                    }

                }
                else if (BitConverter.ToInt16(len, 0)<2048)
                
                {
                    if (buf == null)
                    {
                        buf = new byte[BitConverter.ToInt16(len, 0)+2];
                        buf[0] = len[0];
                        buf[1] = len[1];
                        buf[2 + received++] = data[offset];
                    }
                    else
                    {
                        if (received != BitConverter.ToInt16(len, 0))
                        {
                            buf[2 + received++] = data[offset];
                        }                       
                    }                   
                }
                else
                {
                    len = BitConverter.GetBytes((short)0);
                    lengthRead = false;
                }
                if (received==BitConverter.ToInt16(len, 0) && lengthRead)
                {
                    len = BitConverter.GetBytes((short)0);
                    tmp.Add(buf);
                    buf = null;
                    lengthRead = false;
                    received = 0;
                }
                offset++;
                count--;
            }
            if (tmp.Count > 0)
            {
                return tmp.ToArray();
            }
            else
            {
                return null;
            }
        }

    }
}
